package cn.tedu.tickets;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author :Colin
 * @version 创建时间: 2021/6/23 14:38
 * 本类用于解决实现接口下多线程售票案例的数据安全问题
 */
public class TestRunnableV2 {
    public static void main(String[] args) {
        TicketRunnableV2 target =new TicketRunnableV2();
//        Thread t1=new Thread(target);
//        Thread t2=new Thread(target);
//        Thread t3=new Thread(target);
//        Thread t4=new Thread(target);
//        t1.start();
//        t2.start();
//        t3.start();
//        t4.start();
       /*线程池ExecutorService 用于存储线程的池子，把新建/启动/关闭线程都交给池子来处理
        exectors用于线程池的工具类，newFixedThreadPool（）---创建一个指定线程数的线程池
        */

        ExecutorService pool= Executors.newFixedThreadPool(5);
        for(int i=1 ; i<6 ; i++ ){
            /*execute（）让线程池的线程来执行任务，每次调用都会启动一个线程*/
            pool.execute(target);
        }




    }
}
class TicketRunnableV2 implements Runnable{
    int tickets = 100;
    /*实现接口的方式，不限制锁对象的类型，只需要保持锁对象的唯一
        也就是提取到成员位置创建对象即可，因为target对象只创建一次*/
        Object o=new Object();

    @Override
    /*if一个方法中的所有代码均需要被动不，那么可以用sychronized修饰
    * 被synchronized修饰的方法叫做同步方法
    * */
    //synchronized public void run() {
    public void run() {
        while(true){
            //synchronized (new Object){
            /*注意：锁对象必须唯一，此方式不正确，原因：每个线程执行run（）时都会new一个锁对象*/

                synchronized (o){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName()+"="+tickets--);
            }
                if(tickets<=0) break;
            }

        }

    }
}
